/**
 * XappTool iOS Native SDK
 * 免邀请安装归因 SDK
 * 类似 xinstall/openinstall/sharetrace 功能
 * @version 1.0.0
 */

import Foundation
import UIKit
import SystemConfiguration
import CoreTelephony

// MARK: - 配置类
public class XappToolConfig: NSObject {
    public var apiKey: String = ""
    public var apiUrl: String = "https://api.xapptool.cn"
    public var timeout: TimeInterval = 5.0
    public var debug: Bool = false
    public var environment: String = "production"
    public var enableCache: Bool = true
    public var cacheTimeout: TimeInterval = 3600.0
    public var enableCompression: Bool = true
    public var batchRequests: Bool = false
    public var batchSize: Int = 10
    public var batchInterval: TimeInterval = 5.0
    
    public override init() {
        super.init()
    }
}

// MARK: - 设备信息类
public class DeviceInfo: NSObject, Codable {
    public var deviceModel: String = ""
    public var systemName: String = ""
    public var systemVersion: String = ""
    public var deviceType: String = ""
    public var screenWidth: CGFloat = 0
    public var screenHeight: CGFloat = 0
    public var scale: CGFloat = 0
    public var language: String = ""
    public var region: String = ""
    public var timezone: String = ""
    public var deviceId: String = ""
    public var bundleId: String = ""
    public var appVersion: String = ""
    public var appName: String = ""
    public var isSimulator: Bool = false
    public var isJailbroken: Bool = false
    
    enum CodingKeys: String, CodingKey {
        case deviceModel, systemName, systemVersion, deviceType
        case screenWidth, screenHeight, scale, language, region, timezone
        case deviceId, bundleId, appVersion, appName, isSimulator, isJailbroken
    }
}

// MARK: - 安装参数类
public class InstallParams: NSObject, Codable {
    public var inviter: String?
    public var channel: String?
    public var params: [String: String] = [:]
    public var attributionType: String = "organic"
    public var confidence: Double = 0.0
    public var timestamp: TimeInterval = Date().timeIntervalSince1970
    
    enum CodingKeys: String, CodingKey {
        case inviter, channel, params, attributionType, confidence, timestamp
    }
    
    public override init() {
        super.init()
    }
}

// MARK: - 回调协议
public protocol XappToolCallback: AnyObject {
    func onSuccess<T>(_ result: T)
    func onError(_ error: String)
}

// MARK: - 主SDK类
public class XappTooliOS: NSObject {
    
    private static let SDK_VERSION = "1.0.0"
    private static let PREFS_NAME = "xapptool_prefs"
    private static let KEY_DEVICE_FINGERPRINT = "device_fingerprint"
    private static let KEY_SESSION_ID = "session_id"
    
    private var config: XappToolConfig!
    private var context: URLSession!
    private var isInitialized: Bool = false
    private var deviceFingerprint: String = ""
    private var sessionId: String = ""
    private var deviceInfo: DeviceInfo!
    private var cache: UserDefaults!
    
    // 单例模式
    public static let shared = XappTooliOS()
    
    private override init() {
        super.init()
        self.context = URLSession.shared
        self.cache = UserDefaults.standard
    }
    
    /**
     * 配置SDK
     */
    public func configure(_ config: XappToolConfig) {
        self.config = config
        
        // 获取设备信息
        self.deviceInfo = getDeviceInfo()
        
        // 生成或获取设备指纹
        if let cachedFingerprint = cache.string(forKey: KEY_DEVICE_FINGERPRINT) {
            self.deviceFingerprint = cachedFingerprint
        } else {
            self.deviceFingerprint = generateDeviceFingerprint()
            cache.set(deviceFingerprint, forKey: KEY_DEVICE_FINGERPRINT)
        }
        
        // 生成会话ID
        self.sessionId = UUID().uuidString
    }
    
    /**
     * 初始化 SDK
     */
    public func init(_ callback: XappToolCallback?) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else { return }
            
            do {
                if self.config == nil || self.config.apiKey.isEmpty {
                    throw NSError(domain: "XappTool", code: 1, userInfo: [NSLocalizedDescriptionKey: "API Key is required"])
                }
                
                self.log("Initializing XappTool iOS SDK...")
                
                // 检查设备是否有效
                if self.deviceInfo.isSimulator || self.deviceInfo.isJailbroken {
                    self.log("Warning: Running on simulator or jailbroken device")
                }
                
                self.isInitialized = true
                self.log("XappTool iOS SDK initialized successfully")
                
                DispatchQueue.main.async {
                    callback?.onSuccess(NSNull())
                }
                
            } catch {
                self.log("SDK initialization failed: \(error.localizedDescription)")
                DispatchQueue.main.async {
                    callback?.onError(error.localizedDescription)
                }
            }
        }
    }
    
    /**
     * 获取安装参数
     */
    public func getInstallParams(_ callback: XappToolCallback?) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else { return }
            
            do {
                if !self.isInitialized {
                    throw NSError(domain: "XappTool", code: 2, userInfo: [NSLocalizedDescriptionKey: "SDK not initialized"])
                }
                
                // 检查缓存
                if self.config.enableCache {
                    if let cached = self.getCache("install_params_\(self.deviceFingerprint)") {
                        if let params = try? JSONDecoder().decode(InstallParams.self, from: cached.data(using: .utf8)!) {
                            DispatchQueue.main.async {
                                callback?.onSuccess(params)
                            }
                            return
                        }
                    }
                }
                
                // 构建请求数据
                var requestData: [String: Any] = [
                    "apiKey": self.config.apiKey,
                    "deviceFingerprint": self.deviceFingerprint,
                    "sessionId": self.sessionId,
                    "deviceInfo": try self.encodeDeviceInfo(),
                    "timestamp": Date().timeIntervalSince1970 * 1000
                ]
                
                // 发送归因请求
                self.sendRequest("/api/v1/attribution", requestData) { [weak self] result in
                    guard let self = self else { return }
                    
                    switch result {
                    case .success(let data):
                        do {
                            let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
                            
                            if let code = json["code"] as? Int, code == 0 {
                                if let dataDict = json["data"] as? [String: Any] {
                                    let params = InstallParams()
                                    params.inviter = dataDict["inviter"] as? String
                                    params.channel = dataDict["channel"] as? String
                                    params.attributionType = dataDict["attributionType"] as? String ?? "organic"
                                    params.confidence = dataDict["confidence"] as? Double ?? 0.0
                                    params.timestamp = dataDict["timestamp"] as? TimeInterval ?? Date().timeIntervalSince1970
                                    
                                    if let paramsDict = dataDict["params"] as? [String: String] {
                                        params.params = paramsDict
                                    }
                                    
                                    // 缓存结果
                                    if self.config.enableCache {
                                        if let cachedData = try? JSONEncoder().encode(params) {
                                            let cachedString = String(data: cachedData, encoding: .utf8) ?? ""
                                            self.setCache("install_params_\(self.deviceFingerprint)", cachedString, timeout: self.config.cacheTimeout)
                                        }
                                    }
                                    
                                    DispatchQueue.main.async {
                                        callback?.onSuccess(params)
                                    }
                                } else {
                                    throw NSError(domain: "XappTool", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid response data"])
                                }
                            } else {
                                let message = json["message"] as? String ?? "Request failed"
                                throw NSError(domain: "XappTool", code: 4, userInfo: [NSLocalizedDescriptionKey: message])
                            }
                            
                        } catch {
                            self.handleError(error, callback: callback)
                        }
                        
                    case .failure(let error):
                        self.handleError(error, callback: callback)
                    }
                }
                
            } catch {
                self.handleError(error, callback: callback)
            }
        }
    }
    
    /**
     * 生成邀请链接
     */
    public func generateInvitationLink(_ options: [String: Any], _ callback: XappToolCallback?) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else { return }
            
            do {
                if !self.isInitialized {
                    throw NSError(domain: "XappTool", code: 2, userInfo: [NSLocalizedDescriptionKey: "SDK not initialized"])
                }
                
                let userId = options["userId"] as? String ?? ""
                var code = options["code"] as? String ?? ""
                let channel = options["channel"] as? String ?? "direct"
                let params = options["params"] as? [String: String] ?? [:]
                let expireDays = options["expireDays"] as? Int ?? 7
                
                if code.isEmpty {
                    code = UUID().uuidString.prefix(8).lowercased()
                }
                
                // 构建请求数据
                var requestData: [String: Any] = [
                    "apiKey": self.config.apiKey,
                    "userId": userId,
                    "code": code,
                    "channel": channel,
                    "expireDays": expireDays,
                    "deviceFingerprint": self.deviceFingerprint,
                    "deviceInfo": try self.encodeDeviceInfo()
                ]
                
                if !params.isEmpty {
                    requestData["params"] = params
                }
                
                // 发送请求
                self.sendRequest("/api/v1/invitation-link", requestData) { [weak self] result in
                    guard let self = self else { return }
                    
                    switch result {
                    case .success(let data):
                        do {
                            let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
                            
                            if let code = json["code"] as? Int, code == 0 {
                                if let dataDict = json["data"] as? [String: Any],
                                   let invitationLink = dataDict["invitationLink"] as? String {
                                    DispatchQueue.main.async {
                                        callback?.onSuccess(invitationLink)
                                    }
                                } else {
                                    throw NSError(domain: "XappTool", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid response data"])
                                }
                            } else {
                                let message = json["message"] as? String ?? "Request failed"
                                throw NSError(domain: "XappTool", code: 4, userInfo: [NSLocalizedDescriptionKey: message])
                            }
                            
                        } catch {
                            self.handleError(error, callback: callback)
                        }
                        
                    case .failure(let error):
                        // 生成默认链接
                        let defaultLink = "https://xapptool.cn/invite?userId=\(userId)&code=\(code)&channel=\(channel)"
                        DispatchQueue.main.async {
                            callback?.onSuccess(defaultLink)
                        }
                    }
                }
                
            } catch {
                self.handleError(error, callback: callback)
            }
        }
    }
    
    /**
     * 获取设备指纹
     */
    public func getDeviceFingerprint() -> String {
        return deviceFingerprint
    }
    
    /**
     * 获取设备信息
     */
    public func getDeviceInfo() -> DeviceInfo {
        return deviceInfo
    }
    
    /**
     * 反作弊检测
     */
    public func checkAntiFraud(_ callback: XappToolCallback?) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else { return }
            
            do {
                var results: [String: Any] = [
                    "isSuspicious": false,
                    "reasons": [String](),
                    "isSimulator": self.deviceInfo.isSimulator,
                    "isJailbroken": self.deviceInfo.isJailbroken,
                    "deviceInfo": try self.encodeDeviceInfo()
                ]
                
                var reasons = results["reasons"] as? [String] ?? []
                
                // 综合判断
                if self.deviceInfo.isSimulator {
                    results["isSuspicious"] = true
                    reasons.append("Detected simulator environment")
                }
                
                if self.deviceInfo.isJailbroken {
                    results["isSuspicious"] = true
                    reasons.append("Detected jailbroken device")
                }
                
                results["reasons"] = reasons
                
                DispatchQueue.main.async {
                    callback?.onSuccess(results)
                }
                
            } catch {
                self.handleError(error, callback: callback)
            }
        }
    }
    
    /**
     * 获取渠道统计
     */
    public func getChannelStats(_ options: [String: Any], _ callback: XappToolCallback?) {
        DispatchQueue.global(qos: .background).async { [weak self] in
            guard let self = self else { return }
            
            do {
                if !self.isInitialized {
                    throw NSError(domain: "XappTool", code: 2, userInfo: [NSLocalizedDescriptionKey: "SDK not initialized"])
                }
                
                let startDate = options["startDate"] as? String ?? self.getDefaultStartDate()
                let endDate = options["endDate"] as? String ?? self.getDefaultEndDate()
                let channel = options["channel"] as? String ?? ""
                
                // 构建请求数据
                var requestData: [String: Any] = [
                    "apiKey": self.config.apiKey,
                    "startDate": startDate,
                    "endDate": endDate,
                    "channel": channel,
                    "deviceFingerprint": self.deviceFingerprint,
                    "deviceInfo": try self.encodeDeviceInfo()
                ]
                
                // 发送请求
                self.sendRequest("/api/v1/channel-stats", requestData) { [weak self] result in
                    guard let self = self else { return }
                    
                    switch result {
                    case .success(let data):
                        do {
                            let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
                            
                            if let code = json["code"] as? Int, code == 0 {
                                if let dataDict = json["data"] as? [String: Any] {
                                    DispatchQueue.main.async {
                                        callback?.onSuccess(dataDict)
                                    }
                                } else {
                                    throw NSError(domain: "XappTool", code: 3, userInfo: [NSLocalizedDescriptionKey: "Invalid response data"])
                                }
                            } else {
                                let message = json["message"] as? String ?? "Request failed"
                                throw NSError(domain: "XappTool", code: 4, userInfo: [NSLocalizedDescriptionKey: message])
                            }
                            
                        } catch {
                            self.handleError(error, callback: callback)
                        }
                        
                    case .failure(let error):
                        // 返回默认数据
                        let defaultStats: [String: Any] = [
                            "totalInstalls": 0,
                            "channelStats": [],
                            "conversionRate": 0
                        ]
                        DispatchQueue.main.async {
                            callback?.onSuccess(defaultStats)
                        }
                    }
                }
                
            } catch {
                self.handleError(error, callback: callback)
            }
        }
    }
    
    // MARK: - 私有方法
    
    private func getDeviceInfo() -> DeviceInfo {
        let info = DeviceInfo()
        
        // 设备信息
        info.deviceModel = UIDevice.current.model
        info.systemName = UIDevice.current.systemName
        info.systemVersion = UIDevice.current.systemVersion
        info.deviceType = UIDevice.current.model
        
        // 屏幕信息
        let screen = UIScreen.main
        info.screenWidth = screen.bounds.width
        info.screenHeight = screen.bounds.height
        info.scale = screen.scale
        
        // 语言和地区
        info.language = Locale.current.languageCode ?? "unknown"
        info.region = Locale.current.regionCode ?? "unknown"
        info.timezone = TimeZone.current.identifier
        
        // 设备ID
        info.deviceId = UIDevice.current.identifierForVendor?.uuidString ?? generateUUID()
        
        // 应用信息
        if let bundleId = Bundle.main.bundleIdentifier {
            info.bundleId = bundleId
        }
        
        if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
            info.appVersion = appVersion
        }
        
        if let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
            info.appName = appName
        }
        
        // 检测模拟器
        #if targetEnvironment(simulator)
        info.isSimulator = true
        #endif
        
        // 检测越狱
        info.isJailbroken = detectJailbreak()
        
        return info
    }
    
    private func detectJailbreak() -> Bool {
        // 检查常见的越狱文件
        let jailbreakFiles = [
            "/Applications/Cydia.app",
            "/Library/MobileSubstrate/MobileSubstrate.dylib",
            "/bin/bash",
            "/usr/sbin/sshd",
            "/etc/apt",
            "/usr/bin/ssh"
        ]
        
        for file in jailbreakFiles {
            if FileManager.default.fileExists(atPath: file) {
                return true
            }
        }
        
        // 检查是否可以写入系统目录
        let testString = "test"
        do {
            try testString.write(toFile: "/private/jailbreak.txt", atomically: true, encoding: .utf8)
            try FileManager.default.removeItem(atPath: "/private/jailbreak.txt")
            return true
        } catch {
            // 正常情况应该无法写入
        }
        
        return false
    }
    
    private func generateDeviceFingerprint() -> String {
        let info = deviceInfo
        let fingerprintString = "\(info.deviceModel)_\(info.systemVersion)_\(info.screenWidth)x\(info.screenHeight)_\(info.language)_\(info.timezone)_\(info.deviceId)"
        return hashString(fingerprintString)
    }
    
    private func generateUUID() -> String {
        return UUID().uuidString
    }
    
    private func hashString(_ input: String) -> String {
        let data = Data(input.utf8)
        let hash = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) -> String in
            var hash = 0
            for byte in bytes {
                hash = ((hash << 5) - hash) + Int(byte)
                hash = hash & hash
            }
            return String(abs(hash))
        }
        return hash
    }
    
    private func encodeDeviceInfo() throws -> [String: Any] {
        let encoder = JSONEncoder()
        let data = try encoder.encode(deviceInfo)
        return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] ?? [:]
    }
    
    private func sendRequest(_ endpoint: String, _ data: [String: Any], completion: @escaping (Result<Data, Error>) -> Void) {
        let url = URL(string: config.apiUrl + endpoint)!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue(config.apiKey, forHTTPHeaderField: "X-API-Key")
        request.setValue(sessionId, forHTTPHeaderField: "X-Session-ID")
        request.setValue(deviceFingerprint, forHTTPHeaderField: "X-Fingerprint")
        request.setValue(Self.SDK_VERSION, forHTTPHeaderField: "X-SDK-Version")
        request.setValue("ios", forHTTPHeaderField: "X-Platform")
        request.timeoutInterval = config.timeout
        
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: data, options: [])
        } catch {
            completion(.failure(error))
            return
        }
        
        context.dataTask(with: request) { data, response, error in
            if let error = error {
                completion(.failure(error))
                return
            }
            
            guard let data = data else {
                completion(.failure(NSError(domain: "XappTool", code: 5, userInfo: [NSLocalizedDescriptionKey: "No data received"])))
                return
            }
            
            completion(.success(data))
        }.resume()
    }
    
    private func getCache(_ key: String) -> String? {
        if !config.enableCache { return nil }
        
        if let cached = cache.string(forKey: key) {
            let timestamp = cache.double(forKey: "\(key)_timestamp")
            if Date().timeIntervalSince1970 - timestamp < config.cacheTimeout {
                return cached
            }
        }
        return nil
    }
    
    private func setCache(_ key: String, _ value: String, timeout: TimeInterval) {
        if !config.enableCache { return }
        
        cache.set(value, forKey: key)
        cache.set(Date().timeIntervalSince1970, forKey: "\(key)_timestamp")
    }
    
    private func getDefaultStartDate() -> String {
        let thirtyDaysAgo = Date().addingTimeInterval(-30 * 24 * 60 * 60)
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.string(from: thirtyDaysAgo)
    }
    
    private func getDefaultEndDate() -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.string(from: Date())
    }
    
    private func handleError(_ error: Error, callback: XappToolCallback?) {
        log("Error: \(error.localizedDescription)")
        DispatchQueue.main.async {
            callback?.onError(error.localizedDescription)
        }
    }
    
    private func log(_ message: String) {
        if config.debug {
            print("[XappTool iOS] \(message)")
        }
    }
    
    /**
     * 获取版本信息
     */
    public func getVersion() -> String {
        return Self.SDK_VERSION
    }
    
    /**
     * 获取调试信息
     */
    public func getDebugInfo() -> [String: Any] {
        return [
            "version": getVersion(),
            "isInitialized": isInitialized,
            "deviceFingerprint": deviceFingerprint,
            "sessionId": sessionId,
            "deviceInfo": try? encodeDeviceInfo() ?? [:]
        ]
    }
}